﻿/*!
 * \file module.h
 * \date 2023/05/26 9:56
 *
 * \author Yunfeng.Bo
 * Contact: Yunfeng.Bo@qq.com
 *
 * \brief 服务模块接口定义
 *
 * \note
 */

#pragma once

#include "http_srv.h"

/**
 * 基本关系：
 *      节点 (node_t) 定义了基本的通信方案（internal、TCP、HTTP、...）
 *      一个节点包含 0 ~ N 个服务（service_t）
 */
namespace module {

// 服务
class service {
public:
    explicit service(const std::string& name, const std::string& m_version = "v1");
    virtual ~service();

    virtual int  init() = 0;
    virtual void exit() = 0;

    const std::string&  name() { return m_name; }
    const std::string&  version() { return m_version; }
    virtual std::string path_prefix() { return "/" + name() + "/api/" + version(); }

    // 注册服务功能
    virtual int regist_funcs(const std::string& node_path, std::shared_ptr<http_srv>& srv) = 0;

    virtual json::object to_json() {
        json::object n;
        n["name"] = m_name;

        return n;
    }

protected:
    // 服务名称，用于标识和构成访问路径
    std::string m_name;
    // 服务版本号，方便长期维护，默认为 v1
    std::string m_version;
};

// 节点
class node {
public:
    enum class type_t {
        internal = 0,   // 内部节点，一般指 Keeper 自身包含的服务功能
        http     = 1,
        tcp      = 2,
    };

    virtual int  init();
    virtual void exit();

public:
    explicit node(type_t t)
        : m_type(t){};
    virtual ~node() {}

    type_t type() { return m_type; }

    const std::string path_prefix() {
        if (type_t::internal == m_type)
            return "/internal";
        else
            return "";   // TODO 生成 node 中服务功能的访问前缀
    }

    std::shared_ptr<module::service> find_service(const std::string& name) {
        return m_services.contains(name) ? m_services[name] : nullptr;
    }

    // 注册一个服务，提供服务名称，以及服务绑定的端口，并将服务提供的方法，反向注册到 svr 中
    int register_service(std::shared_ptr<service> s, std::shared_ptr<http_srv>& srv) {
        if (s->name().empty())
            return -1;
        m_services[s->name()] = s;

        s->regist_funcs(path_prefix(), srv);

        return 0;
    }

    json::object to_json() {
        json::object n;
        n["type"]        = (int)m_type;
        n["path_prefix"] = path_prefix();

        json::array services;
        for (auto s : m_services)
            services.push_back(s.second->to_json());
        n["services"] = services;

        return n;
    }

protected:
    type_t m_type;   // 节点类型

    // 模块化服务集合
    std::map<std::string, std::shared_ptr<module::service>> m_services;
};
}   // namespace module
